package exquery

import exquery.util.CommonUtil
import exquery.util.FormatResultUtil
import exquery.util.SearchHelper
import org.apache.log4j.Logger
import org.codehaus.groovy.grails.commons.ConfigurationHolder
import exquery.util.ExportExperimentUtil
import setupx.entity.Experiment
import exquery.util.ValidationUtil

class SearchController {

  Logger gLogger = Logger.getLogger(SearchController.class)
  SearchService searchService
  ExperimentInfoService infoService = new ExperimentInfoService()

  def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
  
  // Export service provided by Export plugin
  def exportService
  
  SearchHelper helper = SearchHelper.getInstance()

  def index = {
     gLogger.info 'comming into search index'
     def searchBy = params.cmbSearchBy
     def searchText = params.searchText

     gLogger.info "params :: ${params}"
     gLogger.info "searchBy :: ${searchBy.toString()}"
     gLogger.info "searchText :: ${searchText}"

     gLogger.info 'out from search index'

     def getSXSearchObjectType = CommonUtil.getInstance().getSXSearchObjectType();
     gLogger.info  getSXSearchObjectType
     return [params:params,getSXSearchObjectType:getSXSearchObjectType]
  }


  def search = {

    gLogger.info 'comming into search'
    gLogger.info "params :: ${params}"
    def searchBy = params.cmbSearchBy
    def searchText = params.searchText

    gLogger.info "params :: ${params}"
    gLogger.info "searchBy :: ${searchBy.toString()}"
    gLogger.info "searchText :: ${searchText}"

    if(searchBy==null || searchBy.toString().trim().length()==0 || searchBy.toString().trim().equals("-1") ){
        flash.message = "Error! searchBy parameter is mandatory, Please select any object."
        redirect(action: "index",params:[cmbSearchBy:searchBy,searchText:searchText])
        return
    }else if(searchText==null || searchText.toString().trim().length()==0){
      flash.message = "Error! Value parameter is mandatory, Please enter search value."
      redirect(action: "index",params:[cmbSearchBy:searchBy,searchText:searchText])
      return
    }else if( searchText!=null ){

        gLogger.info searchText.split("[*]").size()

        if(searchBy.toString().equals("SearchAll") ){
            if(searchText.split("[*]").size()==0){
                flash.message = "Error! Invalid search value."
                redirect(action: "index",params:[cmbSearchBy:searchBy,searchText:searchText])
                return
            }else if ( searchText.toString().length() < 3){
                flash.message = "Error! Value parameter required minimum Three(3) characters."
                redirect(action: "index",params:[cmbSearchBy:searchBy,searchText:searchText])
                return
            }

        }else if( !searchBy.toString().equals("SearchAll") && !searchText.toString().equals("*") && !searchText.toString().equals("**") && !ValidationUtil.getInstance().isLong(searchText.toString()) && searchText.toString().length() < 3){
            flash.message = "Error! Value parameter required minimum Three(3) characters."
            redirect(action: "index",params:[cmbSearchBy:searchBy,searchText:searchText])
            return
        }

    }

    def resultData = []

    // Export Result
    if(params?.format && params.format != "html"){
      response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
      response.setHeader("Content-disposition", "attachment; filename=${searchBy}Result.${params.extension}")
      resultData = processSearch(searchBy,searchText,params,true)

      exportService.export(params.format, response.outputStream, resultData.resultList, resultData.fieldList, resultData.labelMap, resultData.formatters, resultData.parameters)
    }else{

      if( params.offset == null || params.offset.toString().equals("0")){
          params.put("offset",0);
      }else{
         params.put("offset",Long.parseLong("0"+ params.offset.toString()) );
      }

      if( params.max == null || params.max.toString().equals("0")){
          params.put("max",10);
      }else{
          params.put("max",Long.parseLong("0"+ params.max.toString()));
      }

      resultData = processSearch(searchBy,searchText,params)
    }


    return [result: resultData,params:params]
  }

  def exportexp={
      gLogger.info 'comming into exportExperiment'
      gLogger.info "params :: ${params}"
      def id = params.id
      def result = []
      if(id!=null){
        if(id.toString().equalsIgnoreCase("export_all")){
          result = Experiment.getAll()
          params.put("isAll",true)
        }else{
          result = Experiment.findAllById(id)
        }
      }
    
      def workBook = ExportExperimentUtil.getInstance().exportExperiment(result,params)
      println workBook
      // Export Result
      if(params?.format && params.format != "html"){
        response.contentType = ConfigurationHolder.config.grails.mime.types[params.format]
        response.setHeader("Content-disposition", "attachment; filename=${id}.${params.extension}")

        File temp = File.createTempFile("${id}", ".${params.extension}");
        temp.deleteOnExit();

        // The Output file is where the xls will be created
        FileOutputStream fOut = new FileOutputStream(temp);
        // Write the XL sheet
        workBook.write(fOut);
        fOut.flush();
        // Done Deal..
        fOut.close();

        response.outputStream << temp.getBytes()
        response.outputStream.flush()
      }
      return
  }

  def showInfo = {

    gLogger.info 'comming into info'
    def infoBy = params.infoBy
    def idValue = params.id

    gLogger.info "params :: ${params}"
    gLogger.info "infoBy :: ${infoBy.toString()}"
    gLogger.info "idValue :: ${idValue}"

    //get the info method name
    String infoMethod = helper.getExperimentInfoMethodName(infoBy)

    gLogger.info "infoMethod :: ${infoMethod}"
    if (infoMethod == null) {
      return [result:["ErrorMsg" : "wrong info criteria, ${g.message(code: infoBy, default: infoBy, encodeAs: "HTML")}"]]
    }

    def resultData = infoService.getExperimentInfo(infoBy,idValue,params)

    return [result: resultData,params:params]
  }

  private def processSearch(def searchBy,def searchText, def params = [:],boolean isExport = false){

      //get the search method name
      String searchMethod = helper.getSearchMethodName(searchBy)

      gLogger.info "searchMethod :: ${searchMethod}"
      if (searchMethod == null) {
        return ["ErrorMsg" : "wrong search criteria, ${searchBy}"]
      }

      //call the service to search the data
      def resultSearch = searchService.search(searchBy, searchText, params)

      Collection<Map<?, ?>> result = resultSearch?.result
      def resultData = null
      resultData = FormatResultUtil.getInstance()."prepare${searchBy}Result"(result,params,isExport)
      
      if( resultSearch?.ErrorMsg != null ){
        resultData.putAt "ErrorMsg",resultSearch?.ErrorMsg
      }

      resultData?.putAt "isPaginate",resultSearch?.isPaginate
      resultData?.putAt "TotalRecordCount",resultSearch?.TotalRecordCount
      resultData?.putAt "isExport",resultSearch?.isExport

      return resultData
  }

  def genericSearch = {
    redirect(actionName:'index',controller: 'genericSearch')
  }

}
